package com.lee.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Lazy;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.ClientDetailsService;
import org.springframework.security.oauth2.provider.client.JdbcClientDetailsService;
import org.springframework.security.oauth2.provider.code.AuthorizationCodeServices;
import org.springframework.security.oauth2.provider.code.InMemoryAuthorizationCodeServices;
import org.springframework.security.oauth2.provider.token.AuthorizationServerTokenServices;
import org.springframework.security.oauth2.provider.token.DefaultTokenServices;
import org.springframework.security.oauth2.provider.token.TokenEnhancerChain;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;

import javax.sql.DataSource;
import java.io.DataOutput;
import java.util.Arrays;


/**
 * @Description TODO
 * @Author winston
 * @DateTime 2021/11/29
 */
@Configuration
@EnableAuthorizationServer
public class AuthorizationServer extends AuthorizationServerConfigurerAdapter {

	@Autowired
	private TokenStore tokenStore;

//	@Autowired
//	private ClientDetailsService clientDetailsService;
	@Autowired
	private AuthenticationManager authenticationManager;
	@Autowired
	private PasswordEncoder passwordEncoder;
	@Autowired
	private DataSource datasource;
	@Autowired
	private JwtAccessTokenConverter jwtAccessTokenConverter;

	@Bean
	ClientDetailsService clientDetailsService() {
		return new JdbcClientDetailsService(datasource);
	}




	/**
	 * 令牌服务,
	 *
	 * @return {@link AuthorizationServerTokenServices}
	 */
	@Bean
	AuthorizationServerTokenServices tokenServices() {
		DefaultTokenServices services = new DefaultTokenServices();
		services.setClientDetailsService(clientDetailsService());
		services.setSupportRefreshToken(true);//支持刷新
		services.setTokenStore(tokenStore);//token保存的位置
		// 从数据库中读取
//		services.setAccessTokenValiditySeconds(60 * 60 * 2);
//		services.setRefreshTokenValiditySeconds(60 * 60 * 24 * 3);

		// jwt配置
		TokenEnhancerChain tokenEnhancerChain = new TokenEnhancerChain();
		tokenEnhancerChain.setTokenEnhancers(Arrays.asList(jwtAccessTokenConverter));
		services.setTokenEnhancer(tokenEnhancerChain);

		return services;
	}

	@Override
	public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
		security.checkTokenAccess("permitAll()")
				.allowFormAuthenticationForClients();
	}

	@Override
	public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
//		clients.inMemory()
//				.withClient("my_client")
//				.secret(passwordEncoder.encode("123"))
//				.authorizedGrantTypes("authorization_code", "refresh_token", "implicit", "password", "client_credentials")
//				.scopes("read:user", "read:msg")
//				.autoApprove(false)
//				.redirectUris("http://client.javaboy.org:8883/login/oauth2/code/javaboy");
		clients.withClientDetails(clientDetailsService());
	}

	@Override
	public void configure(AuthorizationServerEndpointsConfigurer endpoints) {
		endpoints.authenticationManager(authenticationManager)
				.authorizationCodeServices(authorizationCodeServices())
				.tokenServices(tokenServices());
	}

	@Bean
	public  AuthorizationCodeServices authorizationCodeServices() {
		return new InMemoryAuthorizationCodeServices();
	}



}
